#ifndef EVENTLOOP_EVENTLOOP_H
#define EVNETLOOP_EVENTLOOP_H

#include "timer/TimerID.h"
#include "utility/Noncopyable.h"
#include "utility/chrono.h"
#include "utility/func.h"

#include <atomic>
#include <memory>
#include <mutex>

class EventloopProxy;
class IOchannel;
class TimerManager;

class Eventloop
{
public:
    static Eventloop *LOOP_OF_CURRENT_THREAD();

    Eventloop();
    ~Eventloop();

    const EventloopProxy &proxy() const { return *_eventloopProxy; }

    /// @brief run in owner's thread
    void loop();
    void quit();

    void run_in_loop(const TrivialFunc &func);
    void queue_in_loop(const TrivialFunc &func);

    void cancel(const TimerID &timerid);
    TimerID run_after(double delay, const TrivialFunc &callback);
    TimerID run_every(double delay, const TrivialFunc &callback);

    void assert_in_this_thread(const char *func, const char *file, int line) const;
    bool is_in_this_thread() const;
    

private:
    NONCOPYABLE(Eventloop);

    void _call_pending_funcs();

    std::mutex _mutex;
    std::vector<TrivialFunc> _pendingFuncs;
    std::unique_ptr<EventloopProxy> _eventloopProxy;
    std::unique_ptr<TimerManager> _timerManager;
    std::unique_ptr<IOchannel> _wakeChannel;
    const int _tid;
    bool _callingPendingFuncs;
    bool _looping;
    bool _loopOver;
    std::atomic<bool> _quit;
};

inline bool operator==(const Eventloop &lhs, const Eventloop &rhs) {
    return &lhs == &rhs;
}

inline bool operator!=(const Eventloop &lhs, const Eventloop &rhs) {
    return !(&lhs == &rhs);
}

#define ASSERT_IN_THIS_THREAD() \
    assert_in_this_thread(__func__, __FILE__, __LINE__)


#endif